Obyektni tutib olish, validatsiya va dinamik xatti-harakatlar uchun ilg'or JavaScript Proxy patternlarini o'rganing. Amaliy misollar yordamida kod sifati, xavfsizligi va qo'llab-quvvatlanuvchanligini qanday oshirishni bilib oling.
JavaScript Proxy Patternlari: Murakkab Obyekt Tutib Olish va Validatsiya
JavaScript Proxy obyekti - bu asosiy obyekt operatsiyalarini tutib olish va sozlash imkonini beruvchi kuchli xususiyatdir. U obyekt xatti-harakatlari ustidan ko'proq nazoratni ta'minlab, murakkab dizayn patternlari uchun imkoniyatlar ochib beruvchi ilg'or metaprogramlashtirish usullarini qo'llashga imkon beradi. Ushbu maqolada turli Proxy patternlari, ularning validatsiya, tutib olish va dinamik xatti-harakatlarni o'zgartirishdagi qo'llanilish holatlari ko'rib chiqiladi. JavaScript loyihalaringizda Proxylar kod sifati, xavfsizligi va qo'llab-quvvatlanuvchanligini qanday oshirishi mumkinligini ko'rsatish uchun amaliy misollarga chuqurroq kirib boramiz.
JavaScript Proxy'ni Tushunish
Asosan, Proxy obyekti boshqa obyektni (maqsadni) o'rab oladi va ushbu maqsad ustida bajariladigan operatsiyalarni tutib oladi. Bu tutib olishlar "tuzoqlar" (traps) orqali amalga oshiriladi, ular xususiyatni olish, xususiyatni o'rnatish yoki funksiyani chaqirish kabi muayyan operatsiyalar uchun maxsus xatti-harakatlarni belgilaydigan metodlardir. Proxy API obyektlarning standart xatti-harakatlarini o'zgartirish uchun moslashuvchan va kengaytiriladigan mexanizmni taqdim etadi.
Asosiy Tushunchalar
- Target (Maqsad): Proxy o'rab turgan asl obyekt.
- Handler (Boshqaruvchi): "Tuzoq" (trap) metodlarini o'z ichiga olgan obyekt. Har bir tuzoq ma'lum bir operatsiyaga mos keladi.
- Traps (Tuzoqlar): Boshqaruvchi ichidagi obyekt operatsiyalarini tutib oluvchi va sozlovchi metodlar. Keng tarqalgan tuzoqlarga
get,set,applyvaconstructkiradi.
Proxy Yaratish
Proxy yaratish uchun siz Proxy konstruktoridan foydalanasiz, unga maqsad obyekt va boshqaruvchi obyektni argument sifatida uzatasiz:
const target = {};
const handler = {
get: function(target, property, receiver) {
console.log(`Getting property: ${property}`);
return Reflect.get(target, property, receiver);
}
};
const proxy = new Proxy(target, handler);
proxy.name = "John"; // Jurnalga yozadi: Getting property: name
console.log(proxy.name); // Jurnalga yozadi: Getting property: name, keyin John
Keng Tarqalgan Proxy Tuzoqlari
Proxylar turli operatsiyalarni tutib olish uchun bir qator tuzoqlarni taklif qiladi. Quyida eng ko'p ishlatiladigan tuzoqlardan ba'zilari keltirilgan:
get(target, property, receiver): Xususiyatga murojaatni tutib oladi.set(target, property, value, receiver): Xususiyatga qiymat berishni tutib oladi.has(target, property):inoperatorini tutib oladi.deleteProperty(target, property):deleteoperatorini tutib oladi.apply(target, thisArg, argumentsList): Funksiya chaqiruvlarini tutib oladi.construct(target, argumentsList, newTarget):newoperatorini tutib oladi.getPrototypeOf(target):Object.getPrototypeOf()metodini tutib oladi.setPrototypeOf(target, prototype):Object.setPrototypeOf()metodini tutib oladi.isExtensible(target):Object.isExtensible()metodini tutib oladi.preventExtensions(target):Object.preventExtensions()metodini tutib oladi.getOwnPropertyDescriptor(target, property):Object.getOwnPropertyDescriptor()metodini tutib oladi.defineProperty(target, property, descriptor):Object.defineProperty()metodini tutib oladi.ownKeys(target):Object.getOwnPropertyNames()vaObject.getOwnPropertySymbols()metodlarini tutib oladi.
Proxy Patternlari
Endi, keling, ba'zi amaliy Proxy patternlari va ularning qo'llanilishini ko'rib chiqaylik:
1. Validatsiya Proksisi
Validatsiya Proksisi xususiyatga qiymat berishda cheklovlarni amalga oshiradi. U qiymat berishni davom ettirishdan oldin yangi qiymatni tekshirish uchun set tuzog'ini tutib oladi.
Misol: Shaklda foydalanuvchi kiritgan ma'lumotlarni tekshirish.
const user = {};
const validator = {
set: function(target, property, value) {
if (property === 'age') {
if (!Number.isInteger(value) || value < 0 || value > 120) {
throw new Error('Yaroqsiz yosh. Yosh 0 dan 120 gacha bo\'lgan butun son bo\'lishi kerak.');
}
}
target[property] = value;
return true; // Muvaffaqiyatni bildiradi
}
};
const proxy = new Proxy(user, validator);
proxy.name = 'Alice';
proxy.age = 30;
console.log(user);
try {
proxy.age = 'invalid'; // Xatolik yuzaga keltiradi
} catch (error) {
console.error(error.message);
}
Ushbu misolda set tuzog'i age xususiyati 0 dan 120 gacha bo'lgan butun son ekanligini tekshiradi. Agar validatsiya muvaffaqiyatsiz bo'lsa, xatolik yuzaga keladi va noto'g'ri qiymatning berilishini oldini oladi.
Global Misol: Ushbu validatsiya patterni foydalanuvchi kiritmalari turli manbalar va madaniyatlardan kelishi mumkin bo'lgan global ilovalarda ma'lumotlar yaxlitligini ta'minlash uchun zarurdir. Masalan, pochta indekslarini tekshirish mamlakatlar o'rtasida sezilarli darajada farq qilishi mumkin. Validatsiya proksisi foydalanuvchining joylashuviga qarab turli xil validatsiya qoidalarini qo'llab-quvvatlash uchun moslashtirilishi mumkin.
const address = {};
const addressValidator = {
set: function(target, property, value) {
if (property === 'postalCode') {
// Misol: AQSh pochta indeksining oddiy validatsiyasini taxmin qilish
if (!/^[0-9]{5}(?:-[0-9]{4})?$/.test(value)) {
throw new Error('Yaroqsiz AQSh pochta indeksi.');
}
}
target[property] = value;
return true;
}
};
const addressProxy = new Proxy(address, addressValidator);
addressProxy.postalCode = "12345-6789"; // Yaroqli
try {
addressProxy.postalCode = "abcde"; // Yaroqsiz
} catch(e) {
console.log(e);
}
// Xalqaro ilova uchun siz foydalanuvchining mamlakatiga qarab pochta indekslarini
// tekshira oladigan murakkabroq validatsiya kutubxonasidan foydalanishingiz kerak bo'ladi.
2. Jurnalga Yozish (Logging) Proksisi
Jurnalga Yozish Proksisi xususiyatga murojaat qilish va qiymat berishni ushbu operatsiyalarni jurnalga yozish uchun tutib oladi. Bu disk raskadrovka va audit uchun foydalidir.
Misol: Xususiyatga murojaat va o'zgartirishlarni jurnalga yozish.
const data = {
value: 10
};
const logger = {
get: function(target, property) {
console.log(`Xususiyat olinmoqda: ${property}`);
return target[property];
},
set: function(target, property, value) {
console.log(`Xususiyat o'rnatilmoqda: ${property} ga ${value}`);
target[property] = value;
return true;
}
};
const proxy = new Proxy(data, logger);
console.log(proxy.value); // Jurnalga yozadi: Xususiyat olinmoqda: value, keyin 10
proxy.value = 20; // Jurnalga yozadi: Xususiyat o'rnatilmoqda: value ga 20
get va set tuzoqlari murojaat qilinayotgan yoki o'zgartirilayotgan xususiyatni jurnalga yozib, obyekt bilan o'zaro aloqalar izini ta'minlaydi.
Global Misol: Ko'p millatli korporatsiyada jurnalga yozish proksilari turli joylardagi xodimlar tomonidan amalga oshirilgan ma'lumotlarga kirish va o'zgartirishlarni audit qilish uchun ishlatilishi mumkin. Bu muvofiqlik va xavfsizlik maqsadlari uchun juda muhimdir. Jurnal ma'lumotlarida vaqt zonalari ham hisobga olinishi kerak bo'lishi mumkin.
const employeeData = {
name: "John Doe",
salary: 50000
};
const auditLogger = {
get: function(target, property) {
const timestamp = new Date().toISOString();
console.log(`${timestamp} - [GET] Xususiyatga kirilmoqda: ${property}`);
return target[property];
},
set: function(target, property, value) {
const timestamp = new Date().toISOString();
console.log(`${timestamp} - [SET] Xususiyat o'rnatilmoqda: ${property} ga ${value}`);
target[property] = value;
return true;
}
};
const proxiedEmployee = new Proxy(employeeData, auditLogger);
proxiedEmployee.name; // Vaqt belgisi va 'name' ga kirishni jurnalga yozadi
proxiedEmployee.salary = 60000; // Vaqt belgisi va 'salary' o'zgartirilishini jurnalga yozadi
3. Faqat O'qish Uchun Proksi
Faqat O'qish Uchun Proksi xususiyatga qiymat berishni oldini oladi. U set tuzog'ini tutib oladi va agar xususiyatni o'zgartirishga harakat qilinsa, xatolik yuzaga keltiradi.
Misol: Obyektni o'zgarmas qilish.
const config = {
apiUrl: 'https://api.example.com'
};
const readOnly = {
set: function(target, property, value) {
throw new Error(`Xususiyat o'rnatib bo'lmaydi: ${property}. Obyekt faqat o'qish uchun.`);
}
};
const proxy = new Proxy(config, readOnly);
console.log(proxy.apiUrl);
try {
proxy.apiUrl = 'https://newapi.example.com'; // Xatolik yuzaga keltiradi
} catch (error) {
console.error(error.message);
}
Proksiga biron bir xususiyatni o'rnatishga urinish xatolikka olib keladi va obyektning o'zgarmasligini ta'minlaydi.
Global Misol: Ushbu pattern, ayniqsa, global miqyosda tarqalgan ilovalarda ish vaqtida o'zgartirilmasligi kerak bo'lgan konfiguratsiya fayllarini himoya qilish uchun foydalidir. Bir mintaqadagi konfiguratsiyani tasodifan o'zgartirish butun tizimga ta'sir qilishi mumkin.
const globalSettings = {
defaultLanguage: "en",
currency: "USD",
timeZone: "UTC"
};
const immutableHandler = {
set: function(target, property, value) {
throw new Error(`Faqat o'qish uchun mo'ljallangan xususiyatni o'zgartirib bo'lmaydi: ${property}`);
}
};
const immutableSettings = new Proxy(globalSettings, immutableHandler);
console.log(immutableSettings.defaultLanguage); // 'en' ni chiqaradi
// Qiymatni o'zgartirishga urinish xatolik yuzaga keltiradi
// immutableSettings.defaultLanguage = "fr"; // Xato: Faqat o'qish uchun mo'ljallangan xususiyatni o'zgartirib bo'lmaydi: defaultLanguage
4. Virtual Proksi
Virtual Proksi yaratish yoki olish qimmatga tushishi mumkin bo'lgan resursga kirishni nazorat qiladi. U resursni yaratishni haqiqatda kerak bo'lgunga qadar kechiktirishi mumkin.
Misol: Rasmni kechiktirib yuklash (lazy loading).
const image = {
display: function() {
console.log('Rasm ko\'rsatilmoqda');
}
};
const virtualProxy = {
get: function(target, property) {
if (property === 'display') {
console.log('Rasm yaratilmoqda...');
const realImage = {
display: function() {
console.log('Haqiqiy rasm ko\'rsatilmoqda');
}
};
target.display = realImage.display;
return realImage.display;
}
return target[property];
}
};
const proxy = new Proxy(image, virtualProxy);
// Rasm display chaqirilguncha yaratilmaydi.
proxy.display(); // Jurnalga yozadi: Rasm yaratilmoqda..., keyin Haqiqiy rasm ko'rsatilmoqda
Haqiqiy rasm obyekti faqat display metodi chaqirilganda yaratiladi, bu esa keraksiz resurs sarfini oldini oladi.
Global Misol: Mahsulotlarning rasmlarini taqdim etadigan global elektron tijorat veb-saytini ko'rib chiqing. Virtual Proksi yordamida rasmlar faqat foydalanuvchiga ko'rinadigan bo'lganda yuklanishi mumkin, bu esa, ayniqsa, turli mintaqalardagi sekin internet aloqasiga ega foydalanuvchilar uchun tarmoq o'tkazuvchanligini optimallashtiradi va sahifa yuklanish vaqtini yaxshilaydi.
const product = {
loadImage: function() {
console.log("Yuqori aniqlikdagi rasm yuklanmoqda...");
// Katta rasmni yuklashni simulyatsiya qilish
setTimeout(() => {
console.log("Rasm yuklandi");
this.displayImage();
}, 2000);
},
displayImage: function() {
console.log("Rasm ko'rsatilmoqda");
}
};
const lazyLoadProxy = {
get: function(target, property) {
if (property === "displayImage") {
// Darhol yuklash o'rniga, yuklashni kechiktirish
console.log("Rasmni ko'rsatish so'rovi qabul qilindi. Yuklanmoqda...");
target.loadImage();
return function() { /* Qasddan bo'sh */ }; // Darhol bajarilishini oldini olish uchun bo'sh funksiya qaytariladi
}
return target[property];
}
};
const proxiedProduct = new Proxy(product, lazyLoadProxy);
// displayImage ni chaqirish kechiktirilgan yuklash jarayonini ishga tushiradi
proxiedProduct.displayImage();
5. Bekor Qilinadigan Proksi
Bekor Qilinadigan Proksi sizga istalgan vaqtda proksini bekor qilishga imkon beradi va uni yaroqsiz holga keltiradi. Bu obyektga kirishni nazorat qilish kerak bo'lgan xavfsizlikka sezgir stsenariylar uchun foydalidir.
Misol: Resursga vaqtinchalik kirish huquqini berish.
const target = {
secret: 'Bu maxfiy ma\'lumot'
};
const handler = {
get: function(target, property) {
console.log('Maxfiy xususiyatga kirilmoqda');
return target[property];
}
};
const { proxy, revoke } = Proxy.revocable(target, handler);
console.log(proxy.secret); // Jurnalga yozadi: Maxfiy xususiyatga kirilmoqda, keyin Bu maxfiy ma'lumot
revoke();
try {
console.log(proxy.secret); // TypeError xatoligini yuzaga keltiradi
} catch (error) {
console.error(error.message); // Jurnalga yozadi: Bekor qilingan proksida 'get' amalini bajarib bo'lmaydi
}
Proxy.revocable() metodi bekor qilinadigan proksi yaratadi. revoke() funksiyasini chaqirish proksini yaroqsiz holga keltiradi va maqsad obyektga keyingi kirishni oldini oladi.
Global Misol: Global miqyosda taqsimlangan tizimda siz ma'lum bir mintaqada ishlayotgan xizmatga maxfiy ma'lumotlarga vaqtinchalik kirish huquqini berish uchun bekor qilinadigan proksidan foydalanishingiz mumkin. Ma'lum bir vaqtdan so'ng ruxsatsiz kirishni oldini olish uchun proksi bekor qilinishi mumkin.
const sensitiveData = {
apiKey: "SUPER_SECRET_KEY"
};
const handler = {
get: function(target, property) {
console.log("Maxfiy ma'lumotlarga kirilmoqda");
return target[property];
}
};
const { proxy: dataProxy, revoke: revokeAccess } = Proxy.revocable(sensitiveData, handler);
// 5 soniya davomida kirishga ruxsat berish
setTimeout(() => {
revokeAccess();
console.log("Kirish bekor qilindi");
}, 5000);
// Ma'lumotlarga kirishga urinish
console.log(dataProxy.apiKey); // API kalitini jurnalga yozadi
// 5 soniyadan so'ng bu xatolik yuzaga keltiradi
setTimeout(() => {
try {
console.log(dataProxy.apiKey); // Xato: TypeError: Bekor qilingan proksida 'get' amalini bajarib bo'lmaydi
} catch (error) {
console.error(error);
}
}, 6000);
6. Turni O'zgartirish Proksisi
Turni O'zgartirish Proksisi qaytarilgan qiymatni avtomatik ravishda ma'lum bir turga o'zgartirish uchun xususiyatga kirishni tutib oladi. Bu turli xil manbalardan kelgan va nomuvofiq turlarga ega bo'lishi mumkin bo'lgan ma'lumotlar bilan ishlashda foydali bo'lishi mumkin.
Misol: Satr qiymatlarini sonlarga o'zgartirish.
const data = {
price: '10.99',
quantity: '5'
};
const typeConverter = {
get: function(target, property) {
const value = target[property];
if (typeof value === 'string' && !isNaN(Number(value))) {
return Number(value);
}
return value;
}
};
const proxy = new Proxy(data, typeConverter);
console.log(proxy.price + 1); // Jurnalga yozadi: 11.99 (son)
console.log(proxy.quantity * 2); // Jurnalga yozadi: 10 (son)
get tuzog'i xususiyat qiymati songa o'zgartirilishi mumkin bo'lgan satr ekanligini tekshiradi. Agar shunday bo'lsa, u qiymatni qaytarishdan oldin uni songa o'zgartiradi.
Global Misol: Turli formatlash qoidalariga ega bo'lgan API'lardan (masalan, turli sana formatlari yoki valyuta belgilari) keladigan ma'lumotlar bilan ishlaganda, Turni O'zgartirish Proksisi manbadan qat'i nazar, ilovangizda ma'lumotlar barqarorligini ta'minlashi mumkin. Masalan, turli sana formatlarini qayta ishlash va ularning barchasini ISO 8601 formatiga o'tkazish.
const apiData = {
dateUS: "12/31/2023",
dateEU: "31/12/2023"
};
const dateFormatConverter = {
get: function(target, property) {
let value = target[property];
if (property.startsWith("date")) {
// Ham AQSh, ham YI sana formatlarini ISO 8601 ga o'zgartirishga harakat qilish
if (property === "dateUS") {
const [month, day, year] = value.split("/");
value = `${year}-${month}-${day}`;
} else if (property === "dateEU") {
const [day, month, year] = value.split("/");
value = `${year}-${month}-${day}`;
}
return value;
}
return value;
}
};
const proxiedApiData = new Proxy(apiData, dateFormatConverter);
console.log(proxiedApiData.dateUS); // Chiqaradi: 2023-12-31
console.log(proxiedApiData.dateEU); // Chiqaradi: 2023-12-31
Proksilardan Foydalanish bo'yicha Eng Yaxshi Amaliyotlar
- Proksilardan Oqilona Foydalaning: Proksilar kodingizga murakkablik qo'shishi mumkin. Ulardan faqat validatsiyani yaxshilash, jurnalga yozish yoki obyekt xatti-harakatlarini nazorat qilish kabi sezilarli afzalliklarni taqdim etganda foydalaning.
- Ishlash Samaradorligini Hisobga Oling: Proksi tuzoqlari qo'shimcha yuklanishga olib kelishi mumkin. Ayniqsa, ishlash samaradorligi muhim bo'lgan qismlarda Proksilar salbiy ta'sir ko'rsatmasligiga ishonch hosil qilish uchun kodingizni profillang.
- Xatoliklarni To'g'ri Ishlang: Tuzoq metodlaringiz xatoliklarni to'g'ri qayta ishlashini ta'minlang va kerak bo'lganda ma'lumot beruvchi xato xabarlarini taqdim eting.
- Reflect API'dan Foydalaning:
ReflectAPI obyekt operatsiyalarining standart xatti-harakatlarini aks ettiruvchi metodlarni taqdim etadi. Kerak bo'lganda asl xatti-harakatga topshirish uchun tuzoq metodlaringiz ichidaReflectmetodlaridan foydalaning. Bu sizning tuzoqlaringiz mavjud funksionallikni buzmasligini ta'minlaydi. - Proksilaringizni Hujjatlashtiring: Proksilaringizning maqsadi va xatti-harakatlarini, shu jumladan ishlatiladigan tuzoqlar va joriy qilingan cheklovlarni aniq hujjatlashtiring. Bu boshqa dasturchilarga kodingizni tushunish va qo'llab-quvvatlashga yordam beradi.
Xulosa
JavaScript Proksilari obyektlarni ilg'or manipulyatsiya qilish va tutib olish uchun kuchli vositadir. Turli Proxy patternlarini tushunish va qo'llash orqali siz kod sifati, xavfsizligi va qo'llab-quvvatlanuvchanligini oshirishingiz mumkin. Foydalanuvchi kiritmalarini tekshirishdan tortib maxfiy resurslarga kirishni nazorat qilishgacha, Proksilar obyekt xatti-harakatlarini sozlash uchun moslashuvchan va kengaytiriladigan mexanizmni taklif qiladi. Proksilar imkoniyatlarini o'rganar ekansiz, ulardan oqilona foydalanishni va kodingizni puxta hujjatlashtirishni unutmang.
Taqdim etilgan misollar JavaScript Proksilaridan global kontekstda real muammolarni hal qilish uchun qanday foydalanishni ko'rsatadi. Ushbu patternlarni tushunish va qo'llash orqali siz turli xil foydalanuvchilar bazasining ehtiyojlariga javob beradigan yanada mustahkam, xavfsiz va qo'llab-quvvatlanadigan ilovalarni yaratishingiz mumkin. Har doim kodingizning global oqibatlarini hisobga olishni va yechimlaringizni turli mintaqalar va madaniyatlarning o'ziga xos talablariga moslashtirishni unutmang.